#ifndef _KERNELUTILITY__H_
#define _KERNELUTILITY__H_

#include "Textent.h"

namespace KernelUtility
{
	template <class T>
	struct _FindById_ptr : public std::unary_function<T*, bool>
	{
		const long *pId;
		_FindById_ptr(const long &id) : pId(&id){}
		bool operator () (T* tt)
		{
			if (tt->GetId() == *pId)
				return true;
			return false;
		}
	};

	template <class T>
	struct _FindById_ref : public std::unary_function<T, bool>
	{
		const long *pId;
		_FindById_ref(const long &id) : pId(&id){}
		bool operator () (T tt)
		{
			if (tt.GetId() == *pId)
				return true;
			return false;
		}
	};

	template <class T>
	struct _FindByName_ptr : public std::unary_function<T*, bool>
	{
		const CString *name;
		_FindByName_ptr(const CString &str) : name(&str){}
		bool operator () (T *tt)
		{
			if (tt->GetName() == *name)
				return true;
			return false;
		}
	};

	template <class T>
	struct _FindByName_ref : public std::unary_function<T, bool>
	{
		const CString *name;
		_FindByName_ref(const CString &str) : name(&str){}
		bool operator () (T tt)
		{
			if (tt.GetName() == *name)
				return true;
			return false;
		}
	};

	template <class T>
	struct _SortById_ptr : public std::binary_function<const T*, const T*, bool>
	{
		bool operator () (const T *t1, const T *t2) const
		{
			return t1->GetId() > t2->GetId();
		}
	};

	template <class T>
	struct _SortById_ref : public std::binary_function<const T, const T, bool>
	{
		bool operator () (const T t1, const T t2)
		{
			return t1.GetId() < t2.GetId();
		}
	};

	template <class T>
	T* FindByName_ptr(const std::vector<T*> &vec, const CString &str)
	{
		std::vector<T*>::const_iterator it = std::find_if(vec.begin(), vec.end(), _FindByName_ptr<T>(str));
		if (it != vec.end())
			return *it;
		return NULL;
	};

	template <class T>
	T* FindById_ptr(const std::vector<T*> &vec, const long &id)
	{
		std::vector<T*>::const_iterator it = std::find_if(vec.begin(), vec.end(), _FindById_ptr<T>(id));
		if (it != vec.end())
			return *it;
		return NULL;
	};

	template <class T>
	long FindMaxId_ptr(const std::vector<T*> &vec)
	{
		if (vec.empty())
			return 0;
		std::vector<T*> tmp(vec);
		std::sort(tmp.begin(), tmp.end(), _SortById_ptr<T>());
		return tmp.at(0)->GetId();
	};

	template <class T>
	void Release_V_ptr(std::vector<T*> &vec)
	{
		std::for_each(vec.begin(), vec.end(), _Delete_ptr<T>());
	};

	template <class T>
	class TPushMemVar 
	{
	public:
		TPushMemVar(T &var, const T &val)
		{
			m_pVarBackup = &var;
			m_valBackup = var;
			var = val;
		}
		~TPushMemVar()
		{
			*m_pVarBackup = m_valBackup;
		}
	protected:
		T *m_pVarBackup;
		T m_valBackup;
	};

	template <class T>
	struct _Delete_ptr: public std::unary_function<T*, void>
	{
		void operator () (T* ptr)
		{
			if (ptr)
			{
				delete ptr;
				ptr = NULL;
			}
		}
	};

	template <class T>
	struct _Extent_ptr: public std::unary_function<const T*, void>
	{
		TExtent *m_ext;
		_Extent_ptr(TExtent *ext): m_ext(ext){}
		void operator () (const T *ptr)
		{
			m_ext->Add(ptr->GetExtent());
		}
	};

	template <class T>
	struct _Extent_ref: public std::unary_function<const T, void>
	{
		TExtent *m_ext;
		_Extent_ref(TExtent *ext): m_ext(ext){}
		void operator () (const T tt)
		{
			m_ext->Add(tt.GetExtent());
		}
	};

	template <class T>
	void GetExtent_V_ptr(const std::vector<T*> &vec, TExtent &ent)
	{
		std::for_each(vec.begin(), vec.end(), _Extent_ptr<T>(&ent));
	}

	template <class T>
	void GetExtent_V_ref(const std::vector<T> &vec, TExtent &ent)
	{
		std::for_each(vec.begin(), vec.end(), _Extent_ref<T>(&ent));
	}

	template <class T1, class T2>
	struct _Delete_Pair_ptr : public std::unary_function<std::pair<T1, T2*>, void>
	{
		void operator () (std::pair<T1, T2*> pr)
		{
			if (pr.second)
			{
				delete pr.second;
				pr.second = NULL;
			}
		}
	};

	template <class T1, class T2>
	void Release_M_ptr(std::map<T1, T2*> &mp)
	{
		std::for_each(mp.begin(), mp.end(), _Delete_Pair_ptr<T1, T2>());
	}
}

#endif